package com.offdissys.common.redis.service;

import org.redisson.Redisson;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author ZhangHaiWen
 * @title: RedisService
 * @projectName mybatisplustest
 * @description: 字符串格式化 redis数据
 * @date 2021/11/2411:07
 */
public class RedisService implements CacheService{

    private RedisTemplate redisTemplate;

    private JdkSerializationRedisSerializer redisSerializer;

    @Autowired
    private Redisson redisson;

    public RedisService(RedisSerializer redisSerializer,
                        RedisTemplate redisTemplate) {
        redisTemplate.setKeySerializer(redisSerializer);
        redisTemplate.setValueSerializer(redisSerializer);
        redisTemplate.setHashKeySerializer(redisSerializer);
        redisTemplate.setHashValueSerializer(redisSerializer);
        this.redisTemplate = redisTemplate;
        this.redisSerializer = new JdkSerializationRedisSerializer();;
    }

    public RedisSerializer getRedisSerializer(){
        return redisSerializer;
    }

    @Override
    public Boolean expire(Object key, Object value, long seconds) {
        return (Boolean)redisTemplate.execute((RedisCallback<Boolean>) redisConnection -> redisConnection.setEx(getRedisSerializer().serialize(key),seconds,getRedisSerializer().serialize(value)));
    }

    @Override
    public Boolean expire(Object key, long seconds) {
        return (Boolean)redisTemplate.execute((RedisCallback<Boolean>) redisConnection -> redisConnection.keyCommands().expire(getRedisSerializer().serialize(key), seconds));
    }

    @Override
    public Boolean hasKey(Object key) {
        return (Boolean) redisTemplate.execute((RedisCallback<Boolean>) redisConnection -> redisConnection.keyCommands().exists(getRedisSerializer().serialize(key)));
    }

    @Override
    public Object get(Object key) {
        return redisTemplate.execute((RedisCallback<Object>) redisConnection -> getRedisSerializer().deserialize(redisConnection.get(getRedisSerializer().serialize(key))));
    }

    @Override
    public Boolean set(Object key, Object value) {
        return (Boolean)redisTemplate.execute((RedisCallback<Boolean>) redisConnection -> redisConnection.set(getRedisSerializer().serialize(key),getRedisSerializer().serialize(value)));
    }

    @Override
    public long getExpireTime(Object key) {
        return (Long) redisTemplate.execute((RedisCallback) redisConnection-> redisConnection.keyCommands().pTtl(getRedisSerializer().serialize(key),TimeUnit.SECONDS));
    }

    @Override
    public long del(Object key) {
        return (Long) redisTemplate.execute((RedisCallback) redisConnection-> redisConnection.keyCommands().del(getRedisSerializer().serialize(key)));
    }


    @Override
    public void batchSet(Map<Object, Object> map) {
        redisTemplate.executePipelined((RedisCallback<Object>) redisConnection -> {
            Iterator<Map.Entry<Object, Object>> iterator = map.entrySet().iterator();
            while (iterator.hasNext()){
                Map.Entry<Object, Object> next = iterator.next();
                redisConnection.set(getRedisSerializer().serialize(next.getKey()),getRedisSerializer().serialize(next.getValue()));
            }
            List<Object> result = redisConnection.closePipeline();
            return null;
        });
    }

    @Override
    public void delAll() {
        redisTemplate.execute((RedisCallback<Object>) redisConnection -> {
            redisConnection.flushAll();
            return null;
        });
    }

    @Override
    public int keySpaceCount() {
        Integer count = 0;
        Properties p = redisTemplate.getConnectionFactory().getConnection().info("keyspace");
        Enumeration<Object> enumeration = p.elements();
        while (enumeration.hasMoreElements()){
            String dbs = (String)enumeration.nextElement();
            String[] split = dbs.split(",");
            String keyInfo = split[0];
            String keyCount = keyInfo.split("=")[1];
            count+=Integer.valueOf(keyCount);
        }
        return count;
    }

    @Override
    public Properties info() {
        return redisTemplate.getConnectionFactory().getConnection().info();
    }

    @Override
    public void lock(String lockName) {
        redisson.getLock(lockName).lock();
    }

    @Override
    public void releaseLock(String lockName) {
        redisson.getLock(lockName).unlock();
    }
}
